// # JavaScript 构造函数详解

// 构造函数(Constructor)是 JavaScript 中用于创建和初始化对象的特殊函数。下面我将从多个角度详细解析构造函数的概念、用法和特性。

// ## 1. 基本概念

// 构造函数是：
// - 用于创建对象的函数
// - 通常以大写字母开头(约定而非强制)
// - 使用 `new` 关键字调用
// - 初始化新创建的对象

// ## 2. 构造函数的定义方式

// ### 2.1 传统函数形式

// ```javascript
// function Person(name, age) {
//   this.name = name;
//   this.age = age;
  
//   this.greet = function() {
//     console.log(`Hello, my name is ${this.name}`);
//   };
// }

// const john = new Person('John', 30);
// ```

// ### 2.2 ES6 类形式

// ```javascript
// class Person {
//   constructor(name, age) {
//     this.name = name;
//     this.age = age;
//   }
  
//   greet() {
//     console.log(`Hello, my name is ${this.name}`);
//   }
// }

// const jane = new Person('Jane', 28);
// ```

// ## 3. 构造函数的工作原理

// 当使用 `new` 调用函数时，JavaScript 引擎会执行以下步骤：

// 1. 创建一个新的空对象 `{}`
// 2. 将这个新对象的 `[[Prototype]]` 链接到构造函数的 `prototype` 属性
// 3. 将 `this` 绑定到这个新对象
// 4. 执行构造函数中的代码(初始化对象)
// 5. 如果构造函数没有显式返回对象，则返回这个新对象

// ```javascript
// function myNew(constructor, ...args) {
//   // 步骤1: 创建新对象
//   const obj = {};
  
//   // 步骤2: 链接原型
//   Object.setPrototypeOf(obj, constructor.prototype);
  
//   // 步骤3 & 4: 绑定this并执行构造函数
//   const result = constructor.apply(obj, args);
  
//   // 步骤5: 返回对象
//   return result instanceof Object ? result : obj;
// }

// const bob = myNew(Person, 'Bob', 25);
// ```

// ## 4. 构造函数的特性

// ### 4.1 `prototype` 属性

// 每个构造函数都有一个 `prototype` 属性，它指向原型对象：

// ```javascript
// console.log(Person.prototype); // 原型对象
// ```

// ### 4.2 `constructor` 属性

// 原型对象有一个 `constructor` 属性指回构造函数：

// ```javascript
// console.log(Person.prototype.constructor === Person); // true
// ```

// ### 4.3 实例检查

// 使用 `instanceof` 检查对象是否由特定构造函数创建：

// ```javascript
// console.log(john instanceof Person); // true
// ```

// ## 5. 构造函数与普通函数的区别

// | 特性                | 构造函数               | 普通函数               |
// |---------------------|-----------------------|-----------------------|
// | 调用方式            | 必须使用 `new`         | 直接调用              |
// | `this` 指向         | 新创建的对象           | 取决于调用方式        |
// | 返回值              | 默认返回新对象         | 默认返回 `undefined`  |
// | 命名约定            | 首字母大写             | 首字母小写            |
// | 原型链              | 自动设置原型链         | 无特殊原型处理        |

// ## 6. 构造函数的常见用途

// ### 6.1 创建自定义对象

// ```javascript
// function Car(make, model, year) {
//   this.make = make;
//   this.model = model;
//   this.year = year;
// }

// const myCar = new Car('Toyota', 'Camry', 2020);
// ```

// ### 6.2 实现继承

// ```javascript
// function Employee(name, age, position) {
//   Person.call(this, name, age); // 调用父类构造函数
//   this.position = position;
// }

// // 设置原型链
// Employee.prototype = Object.create(Person.prototype);
// Employee.prototype.constructor = Employee;
// ```

// ### 6.3 封装复杂逻辑

// ```javascript
// function Calculator() {
//   this.result = 0;
  
//   this.add = function(x) {
//     this.result += x;
//     return this;
//   };
  
//   this.multiply = function(x) {
//     this.result *= x;
//     return this;
//   };
// }

// const calc = new Calculator();
// calc.add(5).multiply(2);
// console.log(calc.result); // 10
// ```

// ## 7. 构造函数的注意事项

// ### 7.1 忘记使用 `new` 的问题

// ```javascript
// const badPerson = Person('Oops', 99); // 忘记new
// console.log(name); // "Oops" - 污染全局作用域
// ```

// 解决方案：

// ```javascript
// function Person(name, age) {
//   if (!(this instanceof Person)) {
//     return new Person(name, age);
//   }
//   // 正常初始化...
// }
// ```

// ### 7.2 方法重复创建

// ```javascript
// function Person(name) {
//   this.name = name;
//   this.sayHi = function() { /* ... */ }; // 每个实例都会创建新函数
// }
// ```

// 改进方案(使用原型共享方法)：

// ```javascript
// function Person(name) {
//   this.name = name;
// }

// Person.prototype.sayHi = function() { /* ... */ };
// ```

// ### 7.3 私有变量

// 使用闭包实现私有变量：

// ```javascript
// function Person(name) {
//   let privateAge = 0; // 私有变量
  
//   this.getName = function() { return name; };
//   this.getAge = function() { return privateAge; };
//   this.setAge = function(age) { privateAge = age; };
// }

// const p = new Person('Alice');
// console.log(p.name); // undefined
// console.log(p.getName()); // "Alice"
// ```

// ## 8. ES6 类与构造函数的对比

// ES6 类本质上是构造函数的语法糖：

// ```javascript
// class Person {
//   constructor(name) { this.name = name; }
//   greet() { console.log(`Hello, ${this.name}`); }
// }

// // 等价于
// function Person(name) {
//   this.name = name;
// }

// Person.prototype.greet = function() {
//   console.log(`Hello, ${this.name}`);
// };
// ```

// ## 9. 高级构造函数模式

// ### 9.1 单例模式

// ```javascript
// class Singleton {
//   constructor(data) {
//     if (Singleton.instance) {
//       return Singleton.instance;
//     }
    
//     this.data = data;
//     Singleton.instance = this;
//   }
// }

// const s1 = new Singleton('first');
// const s2 = new Singleton('second');
// console.log(s1 === s2); // true
// ```

// ### 9.2 工厂模式

// ```javascript
// class Car {
//   constructor(type) {
//     this.type = type;
//   }
  
//   static create(type) {
//     switch(type) {
//       case 'sedan': return new Sedan();
//       case 'suv': return new SUV();
//       default: throw new Error('Unknown car type');
//     }
//   }
// }

// class Sedan extends Car { /* ... */ }
// class SUV extends Car { /* ... */ }

// const myCar = Car.create('suv');
// ```

// ## 10. 总结

// 构造函数是 JavaScript 面向对象编程的核心概念：
// - 使用 `new` 调用创建新对象
// - 通过 `this` 初始化对象属性
// - 方法可以定义在原型上实现共享
// - ES6 类提供了更清晰的语法
// - 可以结合各种设计模式实现复杂功能

// 理解构造函数的工作原理对于掌握 JavaScript 的对象系统和原型链至关重要。